/*
 * example_atomic.c
 */
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/printk.h>

static void atomic_add_subtract(void)
{
    atomic_t a_atomic;
    atomic_t b_atomic = ATOMIC_INIT(5);
    atomic_set(&a_atomic, 15);
    pr_info("a_atomic=%d, b_atomic=%d\n", atomic_read(&a_atomic), atomic_read(&b_atomic));

    /* subtract one */
    atomic_dec(&a_atomic);
    pr_info("a dec=%d\n", atomic_read(&a_atomic));

    atomic_add(7, &a_atomic);
    pr_info("a add 7=%d\n", atomic_read(&a_atomic));

    /* add one */
    atomic_inc(&b_atomic);
    pr_info("b inc=%d\n", atomic_read(&b_atomic));

    pr_info("a_atomic=%d, b_atomic=%d\n", atomic_read(&a_atomic), atomic_read(&b_atomic));
}

static void bit_set(void)
{
    unsigned long var = 0x0;
    pr_info("val=0x%lx\n", var);

    set_bit(3, &var);
    pr_info("set bit3: 0x%lx\n", var);

    set_bit(5, &var);
    pr_info("set bit5: 0x%lx\n", var);

    clear_bit(3, &var);
    pr_info("clear bit3: 0x%lx\n", var);

    change_bit(1, &var);
    pr_info("change bit1: 0x%lx\n", var);

    change_bit(1, &var);
    pr_info("change bit1: 0x%lx\n", var);
}


static int __init example_atomic_init(void)
{
    pr_info("example_atomic started\n");

    atomic_add_subtract();
    bit_set();

    return 0;
}

static void __exit example_atomic_exit(void)
{
    pr_info("example_atomic exit\n");
}

module_init(example_atomic_init);
module_exit(example_atomic_exit);

MODULE_DESCRIPTION("Atomic operations example");
MODULE_LICENSE("GPL");
